package com.xiaode.controller.admin.journal;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.jfinal.kit.Ret;
import com.jfinal.plugin.redis.Cache;
import com.jfinal.plugin.redis.Redis;
import com.xiaode.common.constant.Const;
import com.xiaode.common.model.Admin;
import com.xiaode.common.model.dto.log.AdminLogDTO;
import com.xiaode.exce.EnumError;
import com.xiaode.plugin.influx.InfluxDbKit;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.stream.Collectors;

public class JournalService {
    //日志查询
    public Ret findJournal(Date startDate, Date endDate, String name, Integer roleId,String account, Integer page, Integer limit) throws Exception {
        Cache redis = Redis.use();
        boolean flag = false;
        Long startStamp = LocalDateTime.now().minusDays(180).toInstant(ZoneOffset.of("+8")).toEpochMilli() /1000;
        Long endStamp = System.currentTimeMillis() /1000;
        if (startDate != null) {
            Long l = DateUtil.toLocalDateTime(startDate).toInstant(ZoneOffset.of("+8")).toEpochMilli() /1000;
            startStamp = l < startStamp ? startStamp:l;
        }
        if (endDate != null) {
            Long l = DateUtil.toLocalDateTime(endDate).toInstant(ZoneOffset.of("+8")).toEpochMilli()/ 1000;
            if (l < startStamp){
                return Ret.fail().set("error", EnumError.ENDTIME_LOW.getObj());
            }
            endStamp = l;
        }
        //查询目标时间内的记录
        List<AdminLogDTO> aLogList = InfluxDbKit.dbQuery("adminlog", startStamp.toString(), endStamp.toString());
        Set<String> idSet = new HashSet<>();
        if (StrUtil.isNotBlank(name)) {
            List<Admin> adminList = Admin.dao.find("SELECT id,name,roleIds FROM admin WHERE name like concat('%',?,'%') AND isDele = 0", name);
            idSet.addAll(adminList.stream().map(admin -> admin.getId()+"").collect(Collectors.toSet()));
            flag = true;
        }
        //查询角色为roleId的admin
        if (roleId != null){
            List<Admin> admins = Admin.dao.find("SELECT id,roleIds FROM admin WHERE isDele = 0");
            Set<String> adminSet = admins.stream().filter(admin -> JSONUtil.toList(admin.getRoleIds(),Integer.class).contains(roleId)).map(admin -> admin.getId()+"").collect(Collectors.toSet());
            idSet.addAll(adminSet);
            flag = true;
        }
        if (StrUtil.isNotBlank(account)){
            List<Admin> admins = Admin.dao.find("SELECT id,roleIds FROM admin WHERE account = ? AND isDele = 0", account);
            idSet.addAll(admins.stream().map(admin -> admin.getId().toString()).collect(Collectors.toSet()));
            flag = true;
        }

        //如果id不为空
        if (flag) {
            Set<String> finalIdSet = idSet;
            aLogList = aLogList.stream().filter(adminLogDTO -> finalIdSet.contains(adminLogDTO.getAdminId()))
                    .collect(Collectors.toList());
        }
        //总条数
        int size = aLogList.size();
        //分页
        aLogList = aLogList.stream().skip((page - 1) * limit).limit(limit).collect(Collectors.toList());


        //填充属性
        List<Admin> adminList = aLogList.stream().map(adminLogDTO -> {
            Admin o = redis.get(Const.user.Admin + adminLogDTO.getAdminId());
            o.put("url", adminLogDTO.getUrl());
            o.put("methodName", adminLogDTO.getMethodName());
            o.put("remortIP", adminLogDTO.getRemortIP());
            o.put("para", adminLogDTO.getPara());
            o.put("authority", adminLogDTO.getAuthority());
            o.put("state", adminLogDTO.getState());
            o.put("error", adminLogDTO.getErrorMsg());
            if (adminLogDTO.getTimeStamp() != null) {
                o.put("operationTime", new Date(Long.parseLong(adminLogDTO.getTimeStamp())));
            } else {
                o.put("operationTime", "无");
            }
            o.put("field", adminLogDTO.getField());
            return o;
        }).collect(Collectors.toList());

        //解析url
        Map<String, Map<String, String>> pathMethodMap = redis.get("pathMethodMap");
        adminList = adminList.stream().map(admin -> {
            //查询方法
            String url = admin.getStr("url");
            String[] split = url.split("/");
            Map<String, String> methodMap = pathMethodMap.get("/" + split[1]);
            String methodInfos = methodMap.get(split[2]);
            String[] methodInfo = methodInfos.split(":");
            admin.put("type", Integer.parseInt(methodInfo[2]) == 1 ? "查询日志" : "操作日志");
            admin.put("description", methodInfo[1]);
            admin.put("modular", methodInfo[0]);
            return admin;
        }).collect(Collectors.toList());
        return Ret.ok("admin", adminList).set("page", page).set("count", size % limit == 0 ? size / limit : size / limit + 1).set("totalrow", size);
    }
}
